//This file is a part of StoragePlug for Minecraft.
//http://code.google.com/p/minecraft-storageplug/
//StoragePlug is Copyright (C) 2011 Christopher Smith
//Released under the MIT license:
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights 
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//DEALINGS IN THE SOFTWARE.
//
//Related to Minecraft Copyright (C) 2009-2011 Mojang http://www.minecraft.net/

package net.minecraft.storageplug;

import java.io.File;
import java.io.PrintStream;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

public class Command
{
	public static void print_usage()
	{
		System.out.println("StoragePlug command usage:");
		System.out.println(" copy <src dir> <dest dir> - copies data from one directory to another, changing the storage format as needed");
	}
	
	public static void main(String[] args)
		throws Exception
	{
		if(args.length == 0)
		{
			print_usage();
			return;
		}
		
		if(args[0].equals("copy"))
		{
			if(args.length != 3)
				System.out.println("copy requires 2 arguments: <src dir> <dest dir>");
			
			performCopy(args[1], args[2]);
			
			return;
		}
		
		System.out.println("Unknown command: " + args[0]);
		print_usage();
	}
	
	public static void performCopy(String src, String dest)
		throws Exception
	{
		performCopy(new File("storageplug"), new File(src), new File(dest), System.out);
	}
	
	public static void performCopy(File plugin_dir, File src_dir, File dst_dir, PrintStream status)
		throws Exception
	{
		PluginLoader pl = PluginLoader.getPluginLoader();
		
		StorageProvider src = null, dst = null;
		
		try
		{
			src = pl.GetStorageInterface(src_dir);
			dst = pl.GetStorageInterface(dst_dir);

			copyWorldInfos(src, dst, status);
			copyPlayers(src, dst, status);
			copyItemData(src, dst, status);
			copyUniqueIDs(src, dst, status);
			copyChunks(src, dst, status);
            status.println("Closing storage providers.");
		}
		finally
		{
			if(src != null)
				src.dispose();
			if(dst != null)
				dst.dispose();
		}
        status.println("Copy complete.");
	}
	
	static void copyWorldInfos(StorageProvider src, StorageProvider dst, PrintStream status)
		throws Exception
	{
		status.print("Copying world info");
		
		for(Key key : src.iterKeys(Key.WorldInfo.class))
		{
			DataTree dt = src.readDataTree(key);
			dst.writeDataTree(dt, key);
			status.print('.');
		}
		
		status.println();
	}
	
	static void copyPlayers(StorageProvider src, StorageProvider dst, PrintStream status)
		throws Exception
	{
        status.print("Copying ");

        Collection<? extends Key> keys = src.iterKeys(Key.Player.class);
        
        status.print(keys.size() + " players");

		for(Key key : keys)
		{
            if(((Key.Player)key).name == null)
                continue;
			DataTree dt = src.readDataTree(key);
			dst.writeDataTree(dt, key);
			status.print('.');
		}
		
		status.println();
	}
	
	static void copyItemData(StorageProvider src, StorageProvider dst, PrintStream status)
		throws Exception
	{
		status.print("Copying ");

        Collection<? extends Key> keys = src.iterKeys(Key.ItemData.class);
        
        status.print(keys.size() + " item data");
		
		for(Key key : keys)
		{
			DataTree dt = src.readDataTree(key);
			dst.writeDataTree(dt, key);
			status.print('.');
		}
		
		status.println();
	}
	
	static void copyChunks(StorageProvider src, StorageProvider dst, PrintStream status)
		throws Exception
	{
        status.print("Copying ");

        ArrayList<Key> keys = new ArrayList<Key>(1024);
        keys.addAll(src.iterKeys(Key.Chunk.class));
        
        status.print(keys.size() + " chunks");
        
        //load 256 at a time
        for(int i = 0; i < keys.size(); i+=256)
        {
            Collection<? extends Map.Entry<Key, DataTree>> data = src.readDataTreeBatch(keys.subList(i, Math.min(i+256, keys.size())));
            dst.writeDataTreeBatch(data);
            status.print('.');
        }
		
		status.println();
	}

	static void copyUniqueIDs(StorageProvider src, StorageProvider dst, PrintStream status)
		throws Exception
	{
		status.print("Copying unique IDs");
		
		dst.writeUniqueIDs(src.readUniqueIDs());
				
		status.println('.');
	}
}